// msg2pwr.ino is an arduino program meant to be used for an Arduino
// Uno or Nano, connected to a gsm module and to a relais.
//
// When a valid SMS message is received, the relais pin is set to LOW.
// In my configuration this turns _on_ a power socket. After one hour
// the relais pin is set back to HIGH. Any non-valid message also
// sets the relais pin to HIGH.

void praatat();
void do_command(String);
void my_init();
void blink(int);
void halt(String);

#define SerialMon Serial

#include <SoftwareSerial.h>
SoftwareSerial SerialAT(8, 9); // RX, TX

#define TINY_GSM_MODEM_A6
#include <TinyGsmClient.h>
TinyGsm modem(SerialAT);

uint32_t rate = 0;
String header, content;
String tel1 = "+316xxxxxxxx";
String tel2 = "+316xxxxxxxx";
bool validSender = false;
const int relais = 10;
bool ison = false;
unsigned long turnofftime = 0L;

void setup() {
  pinMode(relais, OUTPUT);
  do_command("turn off");

  SerialMon.begin(115200);
  delay(10);

  while (!rate) {
    delay(500L);
    rate = TinyGsmAutoBaud(SerialAT, 2400, 4800);
  }
  SerialAT.begin(rate);

  if (!modem.init()) {
    halt("init() failed.");
  }
  my_init();

  if (!modem.waitForNetwork()) {
    halt("waitForNetwork() failed.");
  }

  SerialMon.println("End of setup(); starting loop().");
  blink(7);
}

void loop() {
  if ( modem.waitResponse(GF("CMT: ")) ) {
    header = SerialAT.readStringUntil('\n');
    content = SerialAT.readString();
    validSender = ( header.indexOf(tel1) + header.indexOf(tel2) >= 0 );
    do_command(content);

    SerialMon.print(" header: "); SerialMon.println(header);
    SerialMon.print(" content: "); SerialMon.println(content);
    if ( validSender ) {
      SerialMon.println("sender is valid");
    } else {
      SerialMon.println("sender is NOT valid");
    }
  }

  if ( ison && millis() > turnofftime ) {
    do_command("turn off");
  }

}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void praatat() {
  while(true) {
    if (SerialAT.available()) {
      SerialMon.write(SerialAT.read());
    }
    if (SerialMon.available()) {
      SerialAT.write(SerialMon.read());
    }
    delay(0);
  }
}

void do_command(String str) {
  if ( validSender && str.charAt(0) == '@' ) {
    digitalWrite(relais, LOW);          // LOW turns on power
    ison = true;
    turnofftime = millis() + 3600000L;  // one hour from now
  } else {
    digitalWrite(relais, HIGH);         // HIGH turns off power
    ison = false;
  }
}

void my_init() {
  modem.sendAT("E1");             // echo on
  modem.waitResponse();
  modem.sendAT("+CMEE=2");        // verbose error messages
  modem.waitResponse();
  modem.sendAT("+CMGF=1");        // sms in text (not pdu) format
  modem.waitResponse();
  modem.sendAT("+CNMI=0,2,0,0");  // write text directly to TE (do not store) 
  modem.waitResponse();
}

void blink(int count) {
  pinMode(13,OUTPUT);
  for ( int i=0 ; i<count ; i++) {
    digitalWrite(13, HIGH);
    delay(700);
    digitalWrite(13, LOW);
    delay(350);
  }
}

void halt(String message) {
  SerialMon.println(message);
  SerialMon.println("Halting.");
  while (1) delay(1000);
}

